package servlet;

import com.alibaba.fastjson.JSONObject;
import entity.User;
import service.Message;
import service.RankingService;
import service.UserService;
import top.ConfigCenter;
import top.RuntimeContextProvider;
import utils.Common;
import utils.JDBCFactory;
import service.RankingService.UserRankPair;

import javax.servlet.ServletException;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.*;
import java.io.IOException;
import java.util.ArrayList;
import java.util.List;

@WebServlet(name = "userServlet", urlPatterns = "*.user", loadOnStartup = 0)
public class UserServlet extends HttpServlet implements HttpSessionListener {

    private static UserService userService =
            RuntimeContextProvider.getContextProvider().getUserService();
    private static RankingService rankingService =
            RuntimeContextProvider.getContextProvider().getRankingService();

    private static final int AUTOLOGINTIME =
            Integer.parseInt(ConfigCenter.getAccountConfig("autoLogingLifeTime"));

    @Override
    public void init() throws ServletException {
        super.init();
    }

    private static void removeCookie(HttpServletRequest req, HttpServletResponse resp) {
        Cookie[] cookies = req.getCookies();
        Cookie loginCookieUname = null;
        Cookie loginCookieUpass = null;

        for(Cookie c : cookies) {
            if(c.getName().equals("username")) loginCookieUname = c;
            if(c.getName().equals("password")) loginCookieUpass = c;
        }

        if(loginCookieUpass != null) {
            loginCookieUpass.setMaxAge(0);
            resp.addCookie(loginCookieUpass);
        }
        if(loginCookieUname != null) {
            loginCookieUname.setMaxAge(0);
            resp.addCookie(loginCookieUname);
        }
    }

    @Override
    protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws IOException {
        req.setCharacterEncoding("UTF-8");
        resp.setContentType("text/html; charset=utf-8");
        switch(req.getServletPath()) {
            case "/autolog.user": {
                if(userService.isLoggedIn(req.getSession()) != null) {
                    resp.getWriter().print(Message.loginSuccess(req.getContextPath() + "/Hall.html"));
                    break;
                }
                Cookie[] cookies = req.getCookies();
                Cookie loginCookieUname = null;
                Cookie loginCookieUpass = null;

                for(Cookie c : cookies) {
                    if(c.getName().equals("username")) loginCookieUname = c;
                    if(c.getName().equals("password")) loginCookieUpass = c;
                }

                if(loginCookieUname != null && loginCookieUpass != null) {
                    String uname    = loginCookieUname.getValue(),
                           upass256 = loginCookieUpass.getValue();

                    if(userService.login(req.getSession(), uname, upass256) != null) {

                        loginCookieUname.setMaxAge(AUTOLOGINTIME);
                        loginCookieUpass.setMaxAge(AUTOLOGINTIME);

                        resp.addCookie(loginCookieUname);
                        resp.addCookie(loginCookieUpass);

                        resp.getWriter().print(Message.loginSuccess(req.getContextPath() + "/Hall.html"));
                        break;
                    }
                }
                resp.getWriter().print(Message.cookieLoginFail());
                break;
            } case "/login.user": {
                String uname    = req.getParameter("username"),
                       upass256 = req.getParameter("password"),
                       autolog  = req.getParameter("autoLogin");

                if(userService.login(req.getSession(), uname, upass256) != null) {
                    if(!Common.isStringEmpty(autolog) && "true".equals(autolog)) {

                        Cookie loginCookieUname = new Cookie("username", uname);
                        Cookie loginCookieUpass = new Cookie("password", upass256);

                        loginCookieUname.setMaxAge(AUTOLOGINTIME);
                        loginCookieUpass.setMaxAge(AUTOLOGINTIME);

                        resp.addCookie(loginCookieUname);
                        resp.addCookie(loginCookieUpass);
                    } else {
                        removeCookie(req, resp);
                    }
                    resp.getWriter().print(Message.loginSuccess(req.getContextPath() + "/Hall.html"));
                } else {
                    resp.getWriter().print(Message.loginFail());
                }
                break;
            } case "/register.user": {
                String  uname    = req.getParameter("username"),
                        upass256 = req.getParameter("password"),
                        unick    = req.getParameter("usernick");
                if(Common.isStringEmpty(uname)) break;
                User newUser = userService.registerLogin(req.getSession(), uname, unick, upass256);
                if(newUser != null) {
                    resp.getWriter().print(Message.loginSuccess(req.getContextPath() + "/userPage.html"));
                } else {
                    resp.getWriter().print(Message.registFail());
                }
                break;
            } case "/password.user": {
                String newPass = req.getParameter("newpass");
                newPass = userService.changePassword(req.getSession(), newPass);
                if (newPass != null) {
                    resp.getWriter().print(Message.passwordChanged());
                } else {
                    resp.getWriter().print(Message.passwordNotChanged());
                }
                break;
            } case "/nick.user": {
                String newNick = req.getParameter("newNick");
                newNick = userService.changeNickname(req.getSession(), newNick);
                if (newNick != null) {
                    resp.getWriter().print(Message.nicknameChanged());
                } else {
                    resp.getWriter().print(Message.nicknameNotChanged());
                }
                break;
            } case "/headPic.user": {
                if(userService.putHeadPic(req) != null) {
                    resp.getWriter().print(Message.headPicChanged());
                } else {
                    resp.getWriter().print(Message.headPicNotChanged());
                }
                break;
            } case "/logout.user": {
                userService.logOut(req.getSession());
                removeCookie(req, resp);
                resp.getWriter().print(Message.logOut(req.getContextPath() + "/battleground.html"));
                break;
            } case "/get.user": {
                User user = userService.getUserInfo(req.getSession());
                Long rank = null;
                Long rankSize = null;
                if(user.getJoinRank() != 0) {
                    rank = rankingService.getRank(user);
                    rankSize = rankingService.getMaxRank();
                }
                resp.getWriter().write(Message.userInfo(user, rank, rankSize));
                return;
            } case "/getRank.user": {
                User user = userService.getUserInfo(req.getSession());
                if(user == null) {
                    resp.getWriter().write(Message.USERLOST);
                    break;
                }
                Long rank = null;
                Long rankSize = null;
                if(user.getJoinRank() != 0) {
                    rank = rankingService.getRank(user);
                    rankSize = rankingService.getMaxRank();
                }
                resp.getWriter().write(Message.userRank(rank, rankSize));
                break;
            } case "/joinRank.user": {
                User user = userService.getUserInfo(req.getSession());
                if(user == null) {
                    resp.getWriter().write(Message.USERLOST);
                    break;
                }
                userService.joinRank(user, true);
                rankingService.put(user);
                resp.getWriter().write(Message.userRank(rankingService.getRank(user), rankingService.getMaxRank()));
                break;
            } case "/exitRank.user": {
                User user = userService.getUserInfo(req.getSession());
                if(user == null) {
                    resp.getWriter().write(Message.USERLOST);
                    break;
                }
                userService.joinRank(user, false);
                rankingService.remove(user);
                break;
            } case "/getRankList.user": {
                String lowStr  = req.getParameter("low");
                String highStr = req.getParameter("high");

                //System.out.println(lowStr + "    " + highStr);

                if(Common.isStringEmpty(lowStr)) break;
                if(Common.isStringEmpty(highStr)) break;

                List<User> list = rankingService.getUsersByRank(Long.parseLong(lowStr), Long.parseLong(highStr));

                JSONObject json = new JSONObject();
                json.put("rankList", list);
                //System.out.println(json.toJSONString());
                resp.getWriter().write(json.toJSONString());
                break;
            } case "/searchRank.user": {
                String unick  = req.getParameter("nick");
                if(Common.isStringEmpty(unick)) break;

                List<User> list = userService.searchByNick(unick);

                List<UserRankPair> userRankList = new ArrayList<>();

                for(User u : list) {
                    if(u.getJoinRank() == 1) {
                        userRankList.add(new UserRankPair(u, rankingService.getRank(u)));
                    }
                }

                JSONObject json = new JSONObject();
                json.put("rankPairList", userRankList);
                //System.out.println(json.toJSONString());
                resp.getWriter().write(json.toJSONString());
                break;
            }
        }
    }

    @Override
    protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
        super.doGet(req, resp);
    }

    @Override
    public void destroy() {
        super.destroy();
        JDBCFactory.destory();
    }

    @Override
    public void sessionCreated(HttpSessionEvent httpSessionEvent) {
        //System.out.println("sessionCreated: " + httpSessionEvent.getSession().getId());
        httpSessionEvent.getSession().setMaxInactiveInterval(1800);
    }

    @Override
    public void sessionDestroyed(HttpSessionEvent httpSessionEvent) {
        //System.out.println("sessionDestroyed: " + httpSessionEvent.getSession().getId());
        userService.logOut(httpSessionEvent.getSession());
    }
}
